package com.etasist;

/**
 * @author issa
 *
 */

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.Collections;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;

import com.etasist.beans.Commands;
import com.etasist.beans.Servers;

public class AgentClient {
	
	public static ClientConfigInfo clientConfigInfo;
	
	public static int i=0;
	
	public static String notAuthorizedCommand="not authorized command!";
	
	public static final String AUTHTYPE_PASSWORD			=	"PASSWORD";
	public static final String AUTHTYPE_ENCRYPTEDPASSWORD	=	"ENCRYPTEDPASSWORD";
	
	public static void main(String[] args) throws IOException {
		
		if (args.length < 1) {
			
			System.out.println("Usage: java com.etasist.AgentCient <configuration file>");
			System.exit(-1);
		}
		
		System.out.println("Initializing configuration...");				
		clientConfigInfo = new ClientConfigInfo(args[0]);

		SwingWorker worker;
		
		Collections.sort(ClientConfigInfo.servers);
		for (i=0; i<ClientConfigInfo.servers.size(); i++){
			try {
				worker = new SwingWorker() {
					int ii = i;
					Servers server = (Servers)ClientConfigInfo.servers.get(ii);
					public Object construct() {
						return doWork(server,ii);
					}

					public void finished() {
					}
				};
				worker.start();

			} catch (Exception ee) {
				ee.printStackTrace();
			}
		}
	}

	public static Object doWork(Servers serv, int servID) {
		String threadName = Thread.currentThread().getName();
		Socket kkSocket = null;
		PrintWriter out = null;
		BufferedReader in = null;
		//String serverIp =serv.getServerIp();
		//int serverPort = Integer.parseInt(serv.getServerPort());
		//ArrayList commandsList = serv.getServerCommands();
		
		Connection conn = null;
		
		Collections.sort(serv.getServerCommands());
		
		String fromServer="";
		String fromUser="";

		try {
			if (Integer.parseInt(serv.getServerPort()) == 22){
				conn = new Connection(serv.getServerIp());
				conn.connect();
				boolean isAuthenticated = false;
				
				if (serv.authtype!=null){
					if(serv.authtype.equalsIgnoreCase(AUTHTYPE_PASSWORD)){
						isAuthenticated = conn.authenticateWithPassword(serv.getUserName(), serv.getPassword());
					} else if(serv.authtype.equalsIgnoreCase(AUTHTYPE_ENCRYPTEDPASSWORD)){
						StringEncrypter decrypter = new StringEncrypter(StringEncrypter.DESEDE_ENCRYPTION_SCHEME);
						isAuthenticated = conn.authenticateWithPassword(serv.getUserName(), decrypter.decrypt(serv.getPassword()));
					} else {
						System.out.println("Authentication failed, not supported authentication type >"+serv.getAuthtype()+"<");
					}
				}
								
				if (isAuthenticated == false)
					throw new IOException("Authentication failed.");

				Session sess = null;

				InputStream stdout = null;
				BufferedReader br = null;

				for (int j = 0; j < serv.getServerCommands().size(); j++) {
					Commands comm = (Commands) serv.getServerCommands().get(j);
					fromUser = comm.getCommand();
					int commID = comm.getCommandID();
					sess = conn.openSession();
					stdout = new StreamGobbler(sess.getStdout());
					br = new BufferedReader(new InputStreamReader(stdout));
					if (fromUser != null) {
						System.out.println("Client (" + servID + ")" + j + ": "+ fromUser);
						sess.execCommand(fromUser);

						while ((fromServer = br.readLine()) != null) {
							System.out.println(threadName+": Server [Srv "+serv.getServerIp()+"][Cmd "+commID+"]: " + fromServer);
						}
						sess.close();
					}
				}
				conn.close();
				
			} else {
				
				try {
					kkSocket = new Socket(serv.getServerIp(), Integer.parseInt(serv.getServerPort()));
					out = new PrintWriter(kkSocket.getOutputStream());
					in = new BufferedReader(new InputStreamReader(kkSocket.getInputStream()));

				} catch (UnknownHostException e) {
					System.err.println("Don't know about host: "+serv.getServerIp()+".");
					System.exit(1);
				} catch (IOException e) {
					System.err.println("Couldn't get I/O for the connection to: "+serv.getServerIp()+".");
					System.exit(1);
				}

				for (int j = 0; j < serv.getServerCommands().size(); j++) {
					Commands comm = (Commands) serv.getServerCommands().get(j);
					fromUser = comm.getCommand();
					int commID = comm.getCommandID();
					if (fromUser != null) {
						System.out.println("Client (" + servID + ")" + j + ": "+ fromUser);
						out.println(fromUser);
						out.flush();
						
						boolean hasEOF = false;
						while (!hasEOF){
						//for (int i = 0; i < 2; i++) {
							if ((fromServer = in.readLine()) != null) {
								System.out.println(threadName+": Server [Srv "+serv.getServerIp()+"][Cmd "+commID+"]: " + fromServer);
								if(fromServer.indexOf(notAuthorizedCommand)>-1){
									break;
								}
								if (fromServer.indexOf("<EOF>")>-1){
									hasEOF=true;
								}
							}
						}
					}
				}
			}
		} catch (IOException ioex) {
			conn.close();
			ioex.printStackTrace(System.err);
		} catch (Exception ex){
			conn.close();
			ex.printStackTrace(System.err);
		}

		try {
			out.println("bye");
			out.flush();
			out.close();
			in.close();
			kkSocket.close();
			conn.close();
		} catch (Exception ex){}
		return "";
	}
}
